#!/usr/bin/env python3

from __future__ import annotations

from sophon_api import SophonClient, Options, abortlog, bytes_to_MiB

import argparse
import pathlib


# This script does currently not write anything to the game installation directory
def parse_args() -> Options:
	parser = argparse.ArgumentParser(description="Game install and update client (WIP)")
	parser.add_argument("gamedir", type=pathlib.Path)
	parser.add_argument("--tempdir", dest="tempdir", type=pathlib.Path)
	parser.add_argument("--force-use-cache", dest="force_use_cache", action="store_true")
	parser.add_argument("--predownload", action="store_true")
	parser.add_argument("--install", dest="install_reltype", type=str, choices=["os", "cn", "bb"])
	parser.add_argument("--select-languages", dest="selected_lang_packs", type=str)
	parser.add_argument("--update", dest="do_update", action="store_true")
	parser.add_argument("--repair", dest="repair_mode", type=str, choices=["quick", "reliable"])

	# Arguments for development / testing. See also: variable description in `sophon_api.py`.
	parser.add_argument("--testing", dest="TESTING_FILE", type=str)
	parser.add_argument("--ignore-conditions", dest="ignore_conditions", action="store_true")
	parser.add_argument("--disallow-download", dest="disallow_download", action="store_true")
	parser.add_argument("--dry-run", dest="dry_run", action="store_true")

	return parser.parse_args(namespace=Options())

def main():
	cli = SophonClient()
	OPT = parse_args()
	cli.initialize(OPT)
	cli.retrieve_API_keys()

	# Which categories to update or install
	todolist = [ "game" ]

	if False:
		# Quick file integrity check
		# TODO: Only works by changing config.ini to an older version.
		cli.load_manifest("game")
		cli.update_config_ini_version()
		exit()

	if OPT.do_update:
		lang_packs = cli.get_voiceover_packs()
		todolist += list(lang_packs)
		print("===> Categories to update:", ", ".join(todolist))

		for p in todolist:
			cli.load_manifest(p)

			if not OPT.predownload:
				cli.process_deletefiles()

			print(f"Category '{p}': {len(cli.di_diffs.manifest.files)} files to update")
			cli.apply_or_prepare_ldiff_files()

			# Also download the missing chunks (new files)
			print(f"Category '{p}': {len(cli.new_files_to_download)} new files to download")
			cli.diff_download_new_files()

			if True:
				print("ENTER TO CONTINUE")
				input()

		if not OPT.predownload:
			cli.load_manifest("game")
			cli.update_config_ini_version()
			cli.remove_ldiff_files()

	if OPT.do_install:
		# Read in the languages. Fuzzy search happens in `cli._select_category`.
		for sel in OPT.selected_lang_packs.split(","):
			sel = sel.strip()
			if len(sel) == 0:
				continue
			todolist.append(sel)

		if len(todolist) == 1:
			abortlog("No voiceover pack(s) selected!")

		print("===> Categories to install:", ", ".join(todolist))

		for p in todolist:
			cli.load_manifest(p)

			download_size_total = cli.get_chunk_download_size(False)
			print(f"Category '{p}': Downloading up to {len(cli.di_chunks.manifest.files)} new files,"
				+ f" {bytes_to_MiB(download_size_total)} MiB")

			for v in cli.di_chunks.manifest.files:
				cli.download_game_file(v)

		cli.update_voiceover_meta_file()
		cli.load_manifest("game")
		cli.update_config_ini_version()

	if OPT.repair_mode:
		lang_packs = cli.get_voiceover_packs()
		todolist += list(lang_packs)
		print("===> Categories to check (& repair):", ", ".join(todolist))

		for p in todolist:
			cli.repair_by_category(p)

			if True:
				print("ENTER TO CONTINUE")
				input()

	#cli.cleanup_temp()


if __name__ == '__main__':
	main()
